package com.tzy.rpc.handler;/**
 * @description:
 * @Author HP
 * @create 2022/3/14 17:19
 */

import com.tzy.rpc.entity.RpcRequest;
import com.tzy.rpc.entity.RpcResponse;
import com.tzy.rpc.enumeration.ResponseCode;
import com.tzy.rpc.provider.ServiceProvider;
import com.tzy.rpc.provider.ServiceProviderImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @author HP
 * @create 2022-03-14 17:19
 * @desc
 **/
public class RequestHandler {
    private static final Logger logger = LoggerFactory.getLogger(RequestHandler.class);

    private static final ServiceProvider serviceProvider;

    static {
        serviceProvider=new ServiceProviderImpl();
    }

    /**
     * 通过输入的rpcRequest对象和对应的实现类，返回执行结果
     * @param rpcRequest 客户端发送的rpcRequest对象
     * @param: service 服务端的实现类
     * @return 执行结果
     */
    public Object handle(RpcRequest rpcRequest) {
        Object result = null;
        //从服务端本地注册表中获取服务实体
        Object service = serviceProvider.getServiceProvider(rpcRequest.getInterfaceName());
        try {
            result = invokeTargetMethod(rpcRequest, service);
            logger.info("服务:{} 成功调用方法:{}", rpcRequest.getInterfaceName(), rpcRequest.getMethodName());
        } catch (IllegalAccessException | InvocationTargetException e) {
            logger.error("调用或发送时有错误发生：", e);
        }
        return RpcResponse.success(result, rpcRequest.getRequestId());
    }

    /**
     * 通过反射进行方法调用，得到服务的实现方法，得到执行结果
     */
    private Object invokeTargetMethod(RpcRequest rpcRequest, Object service) throws IllegalAccessException, InvocationTargetException {
        Object result;
        try {
            Method method = service.getClass().getMethod(rpcRequest.getMethodName(), rpcRequest.getParaTypes());
            result=method.invoke(service, rpcRequest.getParameters());
            logger.info("服务：{}成功调用方法：{}", rpcRequest.getInterfaceName(), rpcRequest.getMethodName());
        } catch (NoSuchMethodException e) {
            return RpcResponse.fail(ResponseCode.NOT_FOUND_METHOD);
        }
        return result;
    }
}
